package com.java.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.java.config.WechatConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;

@Slf4j
@Service
@RequiredArgsConstructor
public class WechatService {
    private final WechatConfig wechatConfig;
    private String accessToken;
    private AtomicLong expireTime = new AtomicLong(0);

    public String getAccessToken() {
        long currentTime = System.currentTimeMillis();
        // 如果access_token不存在或已过期，重新获取
        if (accessToken == null || currentTime >= expireTime.get()) {
            synchronized (this) {
                if (accessToken == null || currentTime >= expireTime.get()) {
                    refreshAccessToken();
                }
            }
        }
        return accessToken;
    }

    private void refreshAccessToken() {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            String url = wechatConfig.getApi().getAccessTokenUrl() +
                    "?grant_type=client_credential" +
                    "&appid=" + wechatConfig.getAppid() +
                    "&secret=" + wechatConfig.getSecret();

            HttpGet httpGet = new HttpGet(url);
            try (CloseableHttpResponse response = httpClient.execute(httpGet)) {
                String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                JSONObject jsonObject = JSON.parseObject(result);
                
                if (jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") != 0) {
                    log.error("获取access_token失败: {}", result);
                    throw new RuntimeException("获取access_token失败: " + result);
                }

                accessToken = jsonObject.getString("access_token");
                // 设置过期时间，提前5分钟过期
                expireTime.set(System.currentTimeMillis() + (jsonObject.getInteger("expires_in") - 300) * 1000L);
                log.info("成功刷新access_token，过期时间：{}", expireTime.get());
            }
        } catch (IOException e) {
            log.error("获取access_token失败", e);
            throw new RuntimeException("获取access_token失败", e);
        }
    }

    public JSONObject getMaterialList(String type, int offset, int count) {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            String url = wechatConfig.getApi().getMaterialListUrl() +
                    "?access_token=" + getAccessToken();

            // 构建请求体
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("type", type);
            requestBody.put("offset", offset);
            requestBody.put("count", count);

            HttpPost httpPost = new HttpPost(url);
            httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
            httpPost.setEntity(new StringEntity(JSON.toJSONString(requestBody), StandardCharsets.UTF_8));

            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
                String result = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
                log.info("获取到的原始响应: {}", result);
                
                JSONObject jsonObject = JSON.parseObject(result);
                
                // 检查access_token是否过期
                if (jsonObject.containsKey("errcode") && jsonObject.getInteger("errcode") == 40001) {
                    // access_token过期，重新获取
                    refreshAccessToken();
                    // 重试请求
                    return getMaterialList(type, offset, count);
                }
                
                return jsonObject;
            }
        } catch (IOException e) {
            log.error("获取素材列表失败", e);
            throw new RuntimeException("获取素材列表失败", e);
        }
    }
} 